from service.rrd import Rrd
from service.PlusterLog import PlusterLog
from service.MainServer import MainServer
from service.pconfig import PConfig
from MVC.plstdocument import IDocument
import threading
import time
import sys
import gc
import socket

class UpdateView:
    "Background update rrd task, no view"
    def __init__(self,ctl):
        pass
    def show(self,master=None):
        pass
    def Update(self,doc):
        pass

class UpdateAdapter:
    "Backgroud update rrd task, no adapter"
    def __init__(self,doc):
        pass
    def handle_request(self):
        pass

class UserSample(PlusterLog):
    def __init__(self,name):
        PlusterLog.__init__(self)
        self.name=name
        self.cpu=0
        self.mem=0
        self.number=0

    def update(self,func):
        """Update by function"""
        cpu,mem=func(self.name)
        self.cpu+=cpu
        self.mem+=mem
        self.number+=1
        self.log.debug("UserSample %s CPU %f Mem %f On Node %d" % \
                           (self.name, cpu, mem, self.number))

    def update_data (self, cpu, mem):
        """ Update by data"""
        self.cpu+=cpu
        self.mem+=mem
        self.number+=1
        self.log.debug("UserSample %s CPU %f Mem %f On Node %d" % \
                           (self.name, cpu, mem, self.number))

    def renew_db(self):
        self.log.debug("User %s CPU %f Mem %f Total Node %d " % \
                           (self.name,
                            self.cpu / self.number,
                            self.mem / self.number,
                            self.number))
        if self.number!=0:
            Rrd.tool.update_user(self.name,self.cpu/self.number,\
                                     self.mem/self.number,self.number)
        self.cpu=0
        self.mem=0
        self.number=0


class UpdateTask(IDocument,PlusterLog,threading.Thread):
    def __init__(self):
        PlusterLog.__init__(self)
        IDocument.__init__(self)
        threading.Thread.__init__(self)
        self.cluster=PConfig.attribute.cluster_name
        self.user_sample_dict={}
        self.cluster_sample=None
        self.setDaemon(False)
        self.log.info("Task __init__ done")

    def config(self,event):
        self.event=event

    def _poll_nodes(self):
        #self.log.info("updating RRD")
        time.sleep(10)
        node_list=MainServer.obj.get_node_list()
        node_number=len(node_list)
        #start=time.time()
        if node_list:
            for node in node_list:
                try:
                    #node_start=time.time()
                    node.update_ps()
                    #update all user data
                    for user in self.user_sample_dict.keys():
                        if node.is_running_user(user):
                            self.user_sample_dict[user].update(node.get_user_usage)
                    #update node
                    cpu,mem,recv,o= node.update_node()
                    self.cluster_sample.update_data(cpu,mem)
                    Rrd.tool.update_node(node.name,cpu,mem,recv,o)
                    Rrd.tool.draw_node(node.name,'-2h','now','icon')
                    node.keep_alive()
                    #node_end=time.time()
                    #self.log.error(node.name+" "+str(node_end-node_start))
                except:
                    mesg="""

Critical Error:

Update Node %s Error, Can not connect Node.

Please check that node.


"""%node.name
                    self.log.critical(mesg)
                    MainServer.obj.KillNode(node.ip,node.port)

            #updete each user db
            self.cluster_sample.renew_db()
            for sample in self.user_sample_dict.values():
                sample.renew_db()

            #end=time.time()
            #self.log.error("allnode "+str(end-start))
            MainServer.obj.Flush()




    def run(self):
        "update node system load and user load"
        for n in PConfig.attribute.get_user_list():
            self.user_sample_dict[n]=UserSample(n)
        self.cluster_sample=UserSample(self.cluster)
        while True:
            try:
                self._poll_nodes()
                gc.collect()
            except:
                print "update error"
                raise
            self.event.wait(10)
            if self.event.isSet():
                print "Update exit"
                break

